package com.weifly.weistock.core.market.impl;

import com.weifly.weistock.core.common.StockException;
import com.weifly.weistock.core.constant.StockCatalogEnum;
import com.weifly.weistock.core.market.StockPriceDto;
import com.weifly.weistock.core.market.StockMarketService;
import com.weifly.weistock.core.util.ConvertUtils;
import com.weifly.weistock.core.util.HttpRequestUtils;
import com.weifly.weistock.core.util.WeistockUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * 股票行情软件
 *
 * @author weifly
 * @since 2019/2/3
 */
public class SinaStockMarketService implements StockMarketService {

    private Logger logger = LoggerFactory.getLogger(SinaStockMarketService.class);

    public static final String STOCK_URL_PREFIX = "http://hq.sinajs.cn/";

    /**
     * 获得股票价格信息
     *
     * @param stockCode
     * @return
     */
    public StockPriceDto getStockPrice(String stockCode) {
        StockCatalogEnum stockCatalog = StockCatalogEnum.getByNumberCode(stockCode);
        if (stockCatalog == null) {
            throw new StockException("不支持证券代码：" + stockCode);
        }
        String fullCode = stockCatalog.getExchangePrefix() + stockCode;
        return this.doGetStockPrice(stockCatalog, fullCode);
    }

    /**
     * 获得股票价格信息
     *
     * @param fullCode
     */
    public StockPriceDto getStockPriceByFullCode(String fullCode) {
        StockCatalogEnum stockCatalog = StockCatalogEnum.getByFullCode(fullCode);
        if (stockCatalog == null) {
            throw new StockException("不支持证券代码：" + fullCode);
        }
        return this.doGetStockPrice(stockCatalog, fullCode);
    }

    private StockPriceDto doGetStockPrice(StockCatalogEnum stockCatalog, String fullCode) {
        // 加载行情信息
        Map<String, String> paramMap = new HashMap<>();
        paramMap.put("list", fullCode);
        Map<String, String> headerMap = new HashMap<>();
        headerMap.put("Referer", "http://finance.sina.com.cn/");
        String stockInfoStr = HttpRequestUtils.sendGet(STOCK_URL_PREFIX, paramMap, headerMap, "GBK");
        if (stockInfoStr == null) {
            return null;
        }
        int startIdx = stockInfoStr.indexOf("\"");
        if (startIdx == -1) {
            return null;
        }
        int endIdx = stockInfoStr.indexOf("\"", startIdx + 1);
        if (endIdx == -1) {
            return null;
        }
        String targetStr = stockInfoStr.substring(startIdx + 1, endIdx);
        String[] infoParts = targetStr.split(",");

        // 解析行情信息
        StockPriceDto priceInfo = new StockPriceDto();
        priceInfo.setStockCatalog(stockCatalog);
        priceInfo.setCode(fullCode);
        priceInfo.setExchangeId(stockCatalog.getExchangeId());
        priceInfo.setMinStepPrice(stockCatalog.getMinStepPrice());
        if (stockCatalog == StockCatalogEnum.HK_STOCK) {
            this.parseHkPriceInfo(priceInfo, infoParts);
        } else if (stockCatalog == StockCatalogEnum.HF_STOCK) {
            this.parseHFPriceInfo(priceInfo, infoParts);
        } else {
            this.parsePriceInfo(priceInfo, infoParts);
        }
        // 去掉name中的空格
        priceInfo.setName(ConvertUtils.removeEmptyChar(priceInfo.getName()));
        return priceInfo;
    }

    private StockPriceDto parsePriceInfo(StockPriceDto priceInfo, String[] infoParts) {
        if (infoParts.length < 32) {
            return null;
        }

        priceInfo.setName(infoParts[0]); // 0 - 证券名称
        // 1 - 开盘价
        priceInfo.setYesterdayClosePrice(Double.valueOf(infoParts[2])); // 2 - 昨天收盘价
        priceInfo.setNowPrice(Double.valueOf(infoParts[3])); // 3 - 最新价
        priceInfo.setHighPrice(Double.valueOf(infoParts[4])); // 4 - 最高价
        priceInfo.setLowPrice(Double.valueOf(infoParts[5])); // 5 - 最低价
        // 6 - 竞买价，即“买一”报价
        // 7 - 竞卖价，即“卖一”报价
        // 8 - 成交的股票数
        // 9 - 成交金额
        // 10 - 买一申请股数
        // 11 - 买一报价
        // 12 - 买二申请股数
        // 13 - 买二报价
        // 14 - 买三申请股数
        // 15 - 买三报价
        // 16 - 买四申请股数
        // 17 - 买四报价
        // 18 - 买五申请股数
        // 19 - 买五报价
        // 20 - 卖一申请股数
        // 21 - 卖一报价
        // 22 - 卖二申请股数
        // 23 - 卖二报价
        // 24 - 卖三申请股数
        // 25 - 卖三报价
        // 26 - 卖四申请股数
        // 27 - 卖四报价
        // 28 - 卖五申请股数
        // 29 - 卖五报价
        priceInfo.setPriceDate(infoParts[30]); // 30 - 日期
        priceInfo.setPriceTime(infoParts[31]); // 31 - 时间
        priceInfo.setUpdateTime(System.currentTimeMillis());

        // 计算涨停、跌停价格
        this.calDownUpPrice(priceInfo);
        return priceInfo;
    }

    private void calDownUpPrice(StockPriceDto priceInfo) {
        Double yesterdayClosePrice = priceInfo.getYesterdayClosePrice();
        if (yesterdayClosePrice == null || yesterdayClosePrice <= 0) {
            return;
        }
        Double minStepPrice = priceInfo.getMinStepPrice();
        double downPrice, upPrice;
        if (minStepPrice == 0.01) {
            downPrice = WeistockUtils.multi(yesterdayClosePrice, 0.9, 2);
            upPrice = WeistockUtils.multi(yesterdayClosePrice, 1.1, 2);
        } else {
            downPrice = WeistockUtils.multi(yesterdayClosePrice, 0.9, 3);
            upPrice = WeistockUtils.multi(yesterdayClosePrice, 1.1, 3);
        }
        priceInfo.setDownPrice(downPrice);
        priceInfo.setUpPrice(upPrice);
    }

    private StockPriceDto parseHkPriceInfo(StockPriceDto priceInfo, String[] infoParts) {
        if (infoParts.length < 19) {
            return null;
        }

        // 0 - SMIC
        // 1 - 中芯国际 证券名称
        priceInfo.setName(infoParts[1]);
        // 2 - 29.700 开盘价
        // 3 - 29.250 昨天收盘价
        priceInfo.setYesterdayClosePrice(Double.valueOf(infoParts[3]));
        // 4 - 31.150 最高价
        priceInfo.setHighPrice(Double.valueOf(infoParts[4]));
        // 5 - 28.950 最低价
        priceInfo.setLowPrice(Double.valueOf(infoParts[5]));
        // 6 - 29.700 最新价
        priceInfo.setNowPrice(Double.valueOf(infoParts[6]));
        // 7 - 0.450
        // 8 - 1.538
        // 9 - 29.700
        // 10 - 29.750
        // 11 - 7324049759.390
        // 12 - 242449499
        // 13 - 96.129
        // 14 - 0.000
        // 15 - 44.800
        // 16 - 11.180
        // 17 - 2021/01/19
        priceInfo.setPriceDate(infoParts[17].replaceAll("/", "-"));
        // 18 - 15:43:04
        priceInfo.setPriceTime(infoParts[18]);
        // ,30|3,N|Y|Y,0.000|0.000|0.000,0|||0.000|0.000|0.000, |0,Y";

        priceInfo.setUpdateTime(System.currentTimeMillis());
        return priceInfo;
    }

    private StockPriceDto parseHFPriceInfo(StockPriceDto priceInfo, String[] infoParts) {
        if (infoParts.length < 14) {
            return null;
        }

        // 0 - 1787.06 最新价
        priceInfo.setNowPrice(Double.valueOf(infoParts[0]));
        // 1 - 1786.200
        // 2 - 1787.06 买1
        // 3 - 1787.57 卖1
        // 4 - 1787.67 最高价
        priceInfo.setHighPrice(Double.valueOf(infoParts[4]));
        // 5 - 1783.20 最低价
        priceInfo.setLowPrice(Double.valueOf(infoParts[5]));
        // 6 - 09:06:00 报价时间
        priceInfo.setPriceTime(infoParts[6]);
        // 7 - 1786.20 昨天收盘价
        priceInfo.setYesterdayClosePrice(Double.valueOf(infoParts[7]));
        // 8 - 1787.22 开盘价
        // 9 - 0,
        // 10- 0,
        // 11- 0,
        // 12- 2021-07-05 报价日期
        priceInfo.setPriceDate(infoParts[12]);
        // 13- 伦敦金（现货黄金） 证券名称
        priceInfo.setName(infoParts[13]);
        priceInfo.setUpdateTime(System.currentTimeMillis());
        return priceInfo;
    }
}
